package com.sdy.auth.biz.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sdy.mvc.service.impl.BaseServiceImpl;
import com.sdy.auth.biz.mapper.SysDeptMapper;
import com.sdy.auth.biz.model.SysDept;
import com.sdy.auth.biz.model.SysUser;
import com.sdy.auth.biz.model.SysUserDept;
import com.sdy.auth.biz.model.vo.LayTreeItem;
import com.sdy.auth.biz.model.vo.UserDeptInfoVo;
import com.sdy.auth.biz.service.SysDeptService;
import com.sdy.auth.biz.service.SysUserDeptService;
import com.sdy.auth.biz.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 组织机构信息表 服务实现类
 * </p>
 *
 * @author zzq
 * @since 2019-06-14
 */
@Slf4j
@Service
public class SysDeptServiceImpl extends BaseServiceImpl<SysDept> implements SysDeptService {
    @Autowired
    private SysDeptMapper sysDeptMapper;
    @Autowired
    private SysUserDeptService sysUserDeptService;
    @Autowired
    private SysUserService sysUserService;

    @Override
    public LayTreeItem getDeptTree() {
        List<SysDept> deptList = list();
        List<LayTreeItem> authList = deptList.stream()
                .map(item -> new LayTreeItem()
                        .setId(item.getId())
                        .setSpread(true)
                        .setTitle(item.getAbbreviation())
                        .setParentId(item.getParentId())
                        .setName(item.getAbbreviation())
                        .setOpen(false))
                .collect(Collectors.toList());
        List<LayTreeItem> rootDept = new ArrayList<>();
        Map<Integer, LayTreeItem> m = new HashMap<>();
        for (LayTreeItem item : authList) {
            m.put(item.getId(), item);
        }
        for (LayTreeItem item : authList) {
            if (item.getParentId() == null || item.getParentId() <= 0) {
                rootDept.add(item);
            } else {
                LayTreeItem parent = m.get(item.getParentId());
                if (parent == null) {
                    rootDept.add(item);
                    break;
                }
                List<LayTreeItem> children = parent.getChildren();
                if (children == null) {
                    children = new ArrayList<>();
                }
                children.add(item);
                parent.setChildren(children);
            }
        }
        return new LayTreeItem().setChildren(rootDept);
    }

    @Override
    public IPage<UserDeptInfoVo> managerPageData(IPage<SysUserDept> page, Map<String, Object> query, Integer deptId) {
        IPage<SysUserDept> userDeptPage = sysUserDeptService.page(page, new QueryWrapper<SysUserDept>().eq("dept_id", deptId).eq("admin", 1));
        if (userDeptPage.getRecords().isEmpty()) {
            return new Page<UserDeptInfoVo>(1, 1, 0).setRecords(new ArrayList<>());
        }
        // 所有用户
        List<Integer> userIdList = userDeptPage.getRecords().stream().map(SysUserDept::getUserId).collect(Collectors.toList());
        List<SysUser> userList = new ArrayList<>(sysUserService.listByIds(userIdList));
        Map<Integer, SysUser> userMap = new HashMap<>();
        userList.forEach(item -> userMap.put(item.getId(), item));

        // 所有组织
        List<SysUserDept> allUserDeptList = sysUserDeptService.list(new QueryWrapper<SysUserDept>().eq("dept_id", deptId));
        List<SysDept> allDeptList = new ArrayList<>(listByIds(allUserDeptList.stream().map(SysUserDept::getDeptId).collect(Collectors.toList())));
        allDeptList.forEach(item -> item.setCode(null).setUniscid(null));
        
        // 用户所属组织
        List<SysUserDept> ownDeptIdList = allUserDeptList.stream().filter(item -> item.getAdmin().equals(2)).collect(Collectors.toList());
        
        // 用户管理的所有组织
        List<SysUserDept> manageDeptIdList = allUserDeptList.stream().filter(item -> item.getAdmin().equals(1)).collect(Collectors.toList());

        // 组装数据
        List<UserDeptInfoVo> resultList = new ArrayList<>();
        for (SysUserDept userDept : userDeptPage.getRecords()) {
            UserDeptInfoVo vo = new UserDeptInfoVo();
            SysUser user = userMap.get(userDept.getUserId());
            vo.setId(user.getId())
                    .setIdCard(user.getIdCard())
                    .setName(user.getName())
                    .setPhone(user.getPhone())
                    .setState(user.getState())
                    .setType(user.getType())
                    .setUserNo(user.getUserNo())
                    .setOwnDeptList(allDeptList.stream().filter(dept -> {
                        for (SysUserDept sysUserDept : ownDeptIdList) {
                            if (sysUserDept.getUserId().equals(user.getId()) && sysUserDept.getDeptId().equals(dept.getId())) {
                                return true;
                            }
                        }
                        return false;
                    }).collect(Collectors.toList()))
                    .setManageDeptList(allDeptList.stream().filter(dept -> {
                        for (SysUserDept sysUserDept : manageDeptIdList) {
                            if (sysUserDept.getUserId().equals(user.getId()) && sysUserDept.getDeptId().equals(dept.getId())) {
                                return true;
                            }
                        }
                        return false;
                    }).collect(Collectors.toList()));
            resultList.add(vo);
        }
        return new Page<UserDeptInfoVo>(userDeptPage.getCurrent(), userDeptPage.getSize(), userDeptPage.getTotal()).setRecords(resultList);
    }

    @Override
    public IPage<UserDeptInfoVo> userPageData(IPage<SysUserDept> page, Map<String, Object> query, Integer deptId) {
        IPage<SysUserDept> userDeptPage = sysUserDeptService.page(page, new QueryWrapper<SysUserDept>().eq("dept_id", deptId).eq("admin", 2));
        if (userDeptPage.getRecords().isEmpty()) {
            return new Page<UserDeptInfoVo>(1, 1, 0).setRecords(new ArrayList<>());
        }
        // 所有用户
        List<Integer> userIdList = userDeptPage.getRecords().stream().map(SysUserDept::getUserId).collect(Collectors.toList());
        List<SysUser> userList = new ArrayList<>(sysUserService.listByIds(userIdList));
        Map<Integer, SysUser> userMap = new HashMap<>();
        userList.forEach(item -> userMap.put(item.getId(), item));

        // 所有组织
        List<SysUserDept> allUserDeptList = sysUserDeptService.list(new QueryWrapper<SysUserDept>().eq("dept_id", deptId));
        List<SysDept> allDeptList = new ArrayList<>(listByIds(allUserDeptList.stream().map(SysUserDept::getDeptId).collect(Collectors.toList())));
        allDeptList.forEach(item -> item.setCode(null).setUniscid(null));

        // 用户所属组织
        List<SysUserDept> ownDeptIdList = allUserDeptList.stream().filter(item -> item.getAdmin().equals(2)).collect(Collectors.toList());

        // 组装数据
        List<UserDeptInfoVo> resultList = new ArrayList<>();
        for (SysUserDept userDept : userDeptPage.getRecords()) {
            SysUser user = userMap.get(userDept.getUserId());
            if (user != null) {
                UserDeptInfoVo vo = new UserDeptInfoVo();
                vo.setId(user.getId())
                        .setIdCard(user.getIdCard())
                        .setName(user.getName())
                        .setPhone(user.getPhone())
                        .setState(user.getState())
                        .setType(user.getType())
                        .setUserNo(user.getUserNo())
                        .setOwnDeptList(allDeptList.stream().filter(dept -> {
                            for (SysUserDept sysUserDept : ownDeptIdList) {
                                if (sysUserDept.getUserId().equals(user.getId()) && sysUserDept.getDeptId().equals(dept.getId())) {
                                    return true;
                                }
                            }
                            return false;
                        }).collect(Collectors.toList()));
                resultList.add(vo);
            }
        }
        return new Page<UserDeptInfoVo>(userDeptPage.getCurrent(), userDeptPage.getSize(), userDeptPage.getTotal()).setRecords(resultList);
    }

    @Override
    public Integer addManagerBatch(List<Integer> userIdList, Integer deptId) {
        if (userIdList.isEmpty() || deptId == null) {
            return 0;
        }
        List<SysUserDept> userDeptList = sysUserDeptService.list(new QueryWrapper<SysUserDept>()
                .eq("dept_id", deptId).in("user_id", userIdList).eq("admin", 1));
        userIdList.removeAll(userDeptList.stream().map(SysUserDept::getUserId).collect(Collectors.toList()));
        if (userIdList.isEmpty()) {
            return 0;
        }
        userIdList.forEach(item -> sysUserDeptService.save(new SysUserDept()
                .setDeptId(deptId)
                .setUserId(item)
                .setAdmin(1)
                .setCreateTime(new Date()))
        );
        return userIdList.size();
    }

    @Override
    public Integer delManagerBatch(List<Integer> userIdList, Integer deptId) {
        if (userIdList.isEmpty() || deptId == null) {
            return 0;
        }
        sysUserDeptService.remove(new QueryWrapper<SysUserDept>()
                .eq("dept_id", deptId).in("user_id", userIdList).eq("admin", 1));
        return userIdList.size();
    }

    @Override
    public List<SysDept> getDeptAccessorList(Integer deptId) {
        List<SysDept> r = new ArrayList<>();
        SysDept dept = getById(deptId);
        r.add(dept);
        String code = dept.getCode();
        while (code.length() > 3) {
            code = code.substring(0, code.length() - 3);
            dept = lambdaQuery().eq(SysDept::getCode, code).one();
            if (dept != null) {
                r.add(dept);
            } else {
                break;
            }
        }
        return r;
    }
}
